package com.erclab.internal.xpresso.webapp.servlets;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;

import com.erclab.internal.xpresso.conf.Settings;
import com.erclab.internal.xpresso.security.User;

public class XUpload extends HttpServlet {

	private static final long serialVersionUID = -6356833964851242789L;
	protected String baseDir;
	
	protected String forwardUrl; 
	
	//	Create the log for this class
	private static final Logger log = Logger.getLogger(FCKEditorConnector.class);	
	
    public void init() throws ServletException { 
		log.info("XUpload initialized. ");
	}
	
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}
	

	/**
	 * Manage the Post requests (FileUpload).<br>
	 *
	 */	
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		log.info("--- XUpload Begin doPost ---");
		this.setBaseDir(request);
		String currentDirPath = getServletContext().getRealPath(baseDir + "/");
		
		log.info("Dir path: " + currentDirPath);
		
		String newName = "";
		forwardUrl = "../jsp/xupload.jsp"; //Default view handler
		
		// Check that we have a file upload request
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
		if (isMultipart){
			log.info("Request is multipart !");
			Enumeration e = request.getHeaderNames();
			while (e.hasMoreElements()){
				String headerName = (String)e.nextElement();
			    log.info( headerName + " : " + request.getHeader(headerName));
			}
			
		} else {
			log.info("The request is NOT multipart - this should not happen");
		}
		
		try {
			// Create a factory for disk-based file items
			FileItemFactory factory = new DiskFileItemFactory();
			log.info("After creating factory");

			//	Create a new file upload handler
			ServletFileUpload upload = new ServletFileUpload(factory);
			log.info("After creating servletFileupload");

			// Parse the request
			List /* FileItem */ items = upload.parseRequest(request);
			log.info("After List");
			
			Map<String, Object> fields = new HashMap<String, Object>();
			log.info("After Map");
			
			log.info("Forward URL is:" +  forwardUrl);
			
			Iterator iter = items.iterator();
			log.info("After iterator");
			log.info("Iterator has next? " + iter.hasNext());
			while (iter.hasNext()) {
				log.info("Iterating on files uploaded");
			    FileItem item = (FileItem) iter.next();
			    String fileNameLong = item.getName();
			    String fieldName = item.getFieldName();
			    log.info("Field Name:" + fieldName);
			    if (!item.isFormField()){
			    	String errorMessage = validateFile(item);
			    	if(errorMessage != null){
			    		sendErrorMessage(errorMessage, request, response);
			    		return;
			    	}			    	
			    	fileNameLong = fileNameLong.replace('\\','/');
					String[] pathParts = fileNameLong.split("/");
					String fileName = pathParts[pathParts.length - 1];
					
					String nameWithoutExt = getNameWithoutExtension(fileName);
					String ext = getExtension(fileName);

					File pathToSave = new File(currentDirPath, fileName);
					int counter = 1;
					log.info("Current dir path: " + currentDirPath);
					while(pathToSave.exists()){
						log.info("File to path exists !");
						newName = nameWithoutExt + "(" + counter + ")" + "." + ext;
						pathToSave = new File(currentDirPath, newName);
						counter++;
						log.info("Path to Save: " + pathToSave);
					}
					item.write(pathToSave);
					if (newName == null || newName.equals("")){
						newName = fileName;
					}
					processFile(item, currentDirPath, fileName);
			    }  else {
					if (item.getFieldName().equals("forwardUrl")){
						forwardUrl = item.getString();
					}
			    }
			}

		} catch (Exception ex) {
			log.error("An error occurred uploading a file: " + ex + " Message:" + ex.getMessage());
			ex.printStackTrace();
		}
	
		log.info("--- End of XUpload post. Forwarding to view ---");
		request.setAttribute("uploadComplete", "true");
		request.setAttribute("imageUrl", ".." + baseDir + newName);
		
		RequestDispatcher view = request.getRequestDispatcher(forwardUrl);
		view.forward(request, response);	
	}
	
	protected void processFile(FileItem item, String path, String filename) {
		// For subclassess to implement if they need to.
		
	}

	protected void sendErrorMessage(String errorMessage, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		log.info("The file uploaded was not valid: " + errorMessage);
		request.setAttribute("error", errorMessage);
		
		RequestDispatcher view = request.getRequestDispatcher(forwardUrl);
		view.forward(request, response);			
	}

	protected String validateFile(FileItem file){
		String contentType = file.getContentType();
		long size = file.getSize();
		log.info("Content type: " + contentType);
		log.info("Size: " + size);
		// In other projects this can be modified.
		// Return null when there is no error
		return null;		
	}

	/*
	 * This method was fixed after Kris Barnhoorn (kurioskronic) submitted SF bug #991489
	 */
  	private String getNameWithoutExtension(String fileName) {
    		return fileName.substring(0, fileName.lastIndexOf("."));
    }
    	
	/*
	 * This method was fixed after Kris Barnhoorn (kurioskronic) submitted SF bug #991489
	 */
	private String getExtension(String fileName) {
		return fileName.substring(fileName.lastIndexOf(".")+1);
	}
	
	protected void setBaseDir(HttpServletRequest request) {
		
		HttpSession session = request.getSession();
		User user = (User)session.getAttribute("user");
		baseDir = Settings.getProperty("upload.path");
		
		String userDirPath = getServletContext().getRealPath(baseDir) + "/" + user.getIdUser();
		
		File currentDir = new File(userDirPath);
		if(!currentDir.exists()){
			currentDir.mkdir();
		}
		baseDir = Settings.getProperty("upload.path") + user.getIdUser()  + "/";
	}	

	
}
